﻿using System;
using System.Text;
using Unknown.Framework.Database;
using Unknown.Framework.Injection;
using Unknown.Framework.Storage;
using Unknown.Source.Entity.Coder;
using Unknown.Source.Entity.NormalView;
using Unknown.Framework.General;

namespace Unknown.Source.Business.Coder
{
    /// <summary>
    /// 数据库代码处理器类
    /// </summary>
    public static class CodeHandler
    {

        /// <summary>
        /// 构建
        /// </summary>
        /// <param name="cascadeTable">级联表</param>
        /// <param name="codeConfigurationKey">代码配置键</param>
        /// <param name="directory">目录</param>
        public static void Build(CascadeTable cascadeTable, string codeConfigurationKey, string directory)
        {
            CodeConfiguration codeConfiguration = null;
            bool has = Preference.CodeConfigurations.ContainsKey(codeConfigurationKey);
            if (has)
            {
                codeConfiguration = Preference.CodeConfigurations[codeConfigurationKey];
            }

            if ((cascadeTable != null) && (cascadeTable.Columns.Count > 0) && (codeConfiguration != null) && (!string.IsNullOrEmpty(codeConfiguration.DataTypeHandler)))
            {
                IDataTypeHandler dataTypeHandler = ObjectFactory.Build(codeConfiguration.DataTypeHandler) as IDataTypeHandler;
                if (dataTypeHandler != null)
                {
                    ClassDescribe classDescribe = ClassDescribeHandler.Build(cascadeTable, codeConfiguration, dataTypeHandler);

                    DotLiquid.RenderParameters parameters = new DotLiquid.RenderParameters();
                    
                    parameters.LocalVariables = new DotLiquid.Hash();
                    parameters.LocalVariables.Add("namespacePrefix", codeConfiguration.NamespacePrefix);
                    parameters.LocalVariables.Add("codeAnalysis", codeConfiguration.CodeAnalysis);
                    parameters.LocalVariables.Add("classDescribe", classDescribe);

                    foreach (Template template in codeConfiguration.Templates)
                    {
                        string templateFile = string.Format(Variable.Culture, "{0}{1}{2}", directory, Variable.PathSeparator, template.File);
                        string templateContent = TextFileHandler.Read(templateFile);
                        if (!string.IsNullOrEmpty(templateContent))
                        {
                            DotLiquid.Template templateHandler = DotLiquid.Template.Parse(templateContent);
                            string sourceContent = templateHandler.Render(parameters);

                            StringBuilder namespaceBuilder = new StringBuilder();
                            namespaceBuilder.Append(codeConfiguration.NamespacePrefix);
                            if (!string.IsNullOrEmpty(template.NamespacePrefix))
                            {
                                namespaceBuilder.Append(".");
                                namespaceBuilder.Append(template.NamespacePrefix);
                            }
                            if (!string.IsNullOrEmpty(classDescribe.NamespaceMap))
                            {
                                namespaceBuilder.Append(".");
                                namespaceBuilder.Append(classDescribe.NamespaceMap);
                            }
                            string className = string.Format(Variable.Culture, "{0}.{1}{2}{3}", namespaceBuilder.ToString(), template.NamePrefix, classDescribe.Name, template.NamePostfix);
                            string sourceFile = string.Format(Variable.Culture, "{0}{1}{2}{1}{3}.{4}", AppDomain.CurrentDomain.BaseDirectory, Variable.PathSeparator, DatabaseHandler.DefaultInstance, className.Replace(".", Variable.PathSeparator), template.Postfix);

                            TextFileHandler.Write(sourceFile, sourceContent);
                        }
                    }
                }
            }
        }
    }
}
